package seg.appx;

import geom.Ellipse;
import geom.Line;
import geom.NullShape;
import geom.Point;
import geom.gVector;
import doc.SampledPoint;

public class Primitive implements Approximator {

	public final double MAX_DIFF = 20;

	private SampledPoint[] points;

	public Primitive() {

	}

	public SampledPoint[] getPoints() {
		return points;
	}

	public void setPoints(SampledPoint[] points) {
		this.points = points;
	}

	public void setPointsBetween(SampledPoint[] ps, int s, int e) {
		points = new SampledPoint[e-s];
		for (int i = 0; i < points.length; i++) {
			points[i] = ps[i+s];
		}
	}

	public double calcDifference() {
		return 0;
	}

	public boolean isApproximate() {
		return false;
	}


	public void calcApproximation() {

	}

	public Point pointAt(double prop) {

		return null;
	}

	public Line normalAt(double prop) {
		gVector v = normalVectorAt(prop).unitized();
		Point p = pointAt(prop);
		if (p == null)
			return null;

		Point p1 = p.add(v.multiply(MAX_DIFF));
		Point p2 = p.add(v.multiply(-MAX_DIFF));
		return new Line(p1, p2);
	}

	public gVector normalVectorAt(double prop) {
		return null;
	}

	public double differneceAt(int i) {
		return 0;
	}

	public double differenceAt(double prop) {
		Line normal = normalAt(prop);
		if (normal == null)
			return 0;

		double max = 0;
		Line line = new Line();
		Point ref = line.getCenter();
		Point intersect;
		for (int i = 1; i < points.length; i++) {
			line.setLine(points[i-1].getX(), points[i-1].getY(),
						 points[i].getX(), points[i].getY());
			intersect = line.intersection(normal);
			if (intersect == null) {
				max = MAX_DIFF;
				break;
			} else {
				double tmp = intersect.distance(ref);
				if (tmp > max)
					max = tmp;
			}
		}
		return max;
	}

	public static final double E_THRES = 2;

	public static final double L_THRES = 2;

	public static final double KK = 10;

	public static Fit fit(SampledPoint[] ps, int s, int e) {
		SampledPoint[] points = new SampledPoint[e-s];
		for (int i = s; i < e; i++) {
			points[i-s] = ps[i];
		}

		Ellipse el = EllipseFit.fit(points);
		double avg = el.avgPtEllipseDist(points);
//		System.err.println("avg of elli = " + avg);
		if (avg < E_THRES) {
//			System.err.println("fit " + el.getMajor() / el.getMinor());
			if (el.getMajor() / el.getMinor() > KK ) {
				return LineFit.fit(points);
			} else {
				return el;
			}
		} else {
			Line line = LineFit.fit(points);
			avg = line.avgPtLineDist(points);
			if (avg < L_THRES)
				return line;
			else
				return new NullShape();
		}
	}

}
